home *** CD-ROM | disk | FTP | other *** search
/ AP Professional Graphics CD-ROM Library / AP Professional Graphics CD-ROM Library.iso / pc / unix / appendix / gemsiii / motblur.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-14  |  7.2 KB  |  199 lines

  1. #include    <string.h>
  2. /*******************************************************************************
  3. The following code implements motion blur on a HP9000 Series 800 computer, 
  4. including computing on fields and compensation for lack of subpixel positioning.
  5. The anti-flicker filter discussed in Section 4 is not included.
  6. In the interests of brevity and clarity, the code presented here is
  7. not the most efficient possible, but note:
  8.  
  9.     1. Rather than initializing the image accumulation buffer to 0 before each
  10.        frame in mb_frame(), the buffer can be initialized to the value of the 
  11.        first subframe.
  12.  
  13.     2. If the number of subframes per field is a power of two, then shifting the
  14.        accumulated result is faster than dividing.
  15.  
  16.     3. If more processing must be done to the image in output(), such as 
  17.        conversion from RGB to YUV, it is most efficient to do the processing
  18.        within the mb_average() routine, rather than to make another pass over 
  19.        the same memory.  
  20.  
  21.     4. Results of the averaging are stored in place in a single accumulation
  22.        buffer.  Depending on the additional processing that must be done by the
  23.        output() procedure, it may be advantageous to store the final result in a
  24.        different buffer instead, such as an array of unsigned char rather than
  25.        unsigned short.
  26. *******************************************************************************/
  27.  
  28. #define FB_STRIDE 2048    /* framebuffer stride -- pixels in a scan line */
  29. #define VID_XRES   640    /* video x resolution */
  30. #define VID_YRES   486    /* video y resolution */
  31.  
  32. /* framebuffer address -- pixels stored in unsigned ints */
  33. /* we assume frame is initialized to point to the memory-mapped framebuffer */
  34. static unsigned int *frame;                     
  35. #define BB(v)  ( ((v) <<24)>>24 )    /* extract blue byte from fb pixel */
  36. #define BG(v)  ( ((v) <<16)>>24 )    /* extract green byte from fb pixel */
  37. #define BR(v)  ( ((v) << 8)>>24 )    /* extract red byte from fb pixel */
  38.  
  39. /* accumulation buffer -- pixels stored as r,g,b, r,g,b,... */
  40. static unsigned short acc[VID_XRES*VID_YRES*3]; 
  41.  
  42. void mb_average(), mb_accumulate();
  43.  
  44. /*******************************************************************************
  45. Compute and output a motion blurred frame.
  46.  
  47. External Procedures:
  48.  
  49.     void shift_image(int x,int y) - adjusts the viewing transformation to
  50.                                     render the image shifted by an integral
  51.                                     number of pixels in x and y 
  52.  
  53.     void draw(double t)           - renders a subframe at time t
  54.  
  55.     void output(unsigned short *acc,int w,int h) - outputs an image (e.g. 
  56.                                                    records a frame of the 
  57.                                                    animation onto the output
  58.                                                    device)
  59.  
  60. Entry:
  61.     t0      - frame start time
  62.     delta   - shutter open time
  63.     n       - number of subframes
  64. *******************************************************************************/
  65. void mb_frame(t0,delta,n)
  66. double t0;
  67. double delta;
  68. int n;
  69. {
  70.     int i;
  71.     int nfield = n/2; /* number of subframes per field */
  72.     int field = 1;    /* current field; first 1, then 0 */
  73.  
  74.     /* pixel offsets for 16 subframes/field, gives triangle filter in x and y */
  75.     static int x_off[] = {0,1,0,1, -1,0,-1,0,  0, 1, 0,1, -1, 0,-1,0};
  76.     static int y_off[] = {0,1,1,0,  0,1, 1,0,  0,-1,-1,0,  0,-1,-1,0};
  77. #define NOFFS ( sizeof(x_off)/sizeof(x_off[0]) )
  78.  
  79.     /* clear accumulation buffer */
  80.     memset((void *)acc,0,sizeof(acc));
  81.  
  82.     for (i = 0; i < n; i++) {
  83.         shift_image(x_off[(i%nfield)%NOFFS],y_off[(i%nfield)%NOFFS]);
  84.         draw(t0 + i*delta/(n-1));
  85.         if (i == nfield-1 || i == n-1) {
  86.             mb_average(nfield,field);
  87.             field = !field;
  88.         } else {  
  89.             mb_accumulate(field);
  90.         }
  91.     }
  92.  
  93.     /* output final image */
  94.     output(acc,VID_XRES,VID_YRES);
  95. }
  96.  
  97. /*******************************************************************************
  98. Add another subframe to the accumulation buffer, computing on fields.  
  99.  
  100. Entry:
  101.     field   - field number (0 or 1)
  102. *******************************************************************************/
  103. void mb_accumulate(field)
  104. int field;
  105. {
  106.     register unsigned int *iptr;
  107.     register unsigned short *optr;
  108.     register int i,j;
  109.  
  110.     /* shift input and output pointers by one scan line if field 1 */
  111.     if (field) {
  112.         iptr = frame + FB_STRIDE;
  113.         optr = acc + 3*VID_XRES;
  114.     } else {
  115.         iptr = frame;
  116.         optr = acc;
  117.     }
  118.  
  119.     /* add in field to accumulation buffer */
  120.     for (i = 0; i < VID_YRES; i+=2) {
  121.         for (j = 0; j < VID_XRES; j+=4) {
  122.             /* process 4 pixels, skipping every other one */
  123.             register unsigned int v1 = iptr[0];
  124.             register unsigned int v3 = iptr[2];
  125.             register unsigned int v5 = iptr[4];
  126.             register unsigned int v7 = iptr[6];
  127.  
  128.             optr[0] += BR(v1); optr[1]  += BG(v1); optr[2]  += BB(v1);
  129.             optr[3] += BR(v3); optr[4]  += BG(v3); optr[5]  += BB(v3);
  130.             optr[6] += BR(v5); optr[7]  += BG(v5); optr[8]  += BB(v5);
  131.             optr[9] += BR(v7); optr[10] += BG(v7); optr[11] += BB(v7);
  132.  
  133.             iptr += 8;
  134.             optr += 12;
  135.         }
  136.         iptr += 4*FB_STRIDE-VID_XRES*2; /* process every fourth scan line */
  137.         optr += 3*VID_XRES;             /* skip to next field scan line */
  138.     }
  139. }
  140.  
  141. /*******************************************************************************
  142. Add another subframe and divide by the number of field subframes.
  143. The result is placed back into the accumulation buffer.
  144.  
  145. Entry:
  146.     n       - number of subframes in a field
  147.     field   - field number (0 or 1)
  148. *******************************************************************************/
  149. void mb_average(n,field)
  150. int n;
  151. int field;
  152. {
  153.     register unsigned int *iptr;
  154.     register unsigned short *optr;
  155.     register int i,j;
  156.  
  157.     /* shift input and output pointers by one scan line if field 1 */
  158.     if (field) {
  159.         iptr = frame + FB_STRIDE;
  160.         optr = acc + 3*VID_XRES;
  161.     } else {
  162.         iptr = frame;
  163.         optr = acc;
  164.     }
  165.  
  166.     /* add in field to accumulation buffer and divide */
  167.     for (i = 0; i < VID_YRES; i+=2) {
  168.         for (j = 0; j < VID_XRES; j+=4) {
  169.             /* process 4 pixels, skipping every other one */
  170.             register unsigned int v1 = iptr[0];
  171.             register unsigned int v3 = iptr[2];
  172.             register unsigned int v5 = iptr[4];
  173.             register unsigned int v7 = iptr[6];
  174.  
  175.             optr[0] = (optr[0]+BR(v1))/n; 
  176.             optr[1] = (optr[1]+BG(v1))/n; 
  177.             optr[2] = (optr[2]+BB(v1))/n;
  178.  
  179.             optr[3] = (optr[3]+BR(v3))/n; 
  180.             optr[4] = (optr[4]+BG(v3))/n; 
  181.             optr[5] = (optr[5]+BB(v3))/n;
  182.  
  183.             optr[6] = (optr[6]+BR(v5))/n; 
  184.             optr[7] = (optr[7]+BG(v5))/n; 
  185.             optr[8] = (optr[8]+BB(v5))/n;
  186.  
  187.             optr[9] = (optr[9]+BR(v7))/n; 
  188.             optr[10] = (optr[10]+BG(v7))/n; 
  189.             optr[11] = (optr[11]+BB(v7))/n;
  190.  
  191.             iptr += 8;
  192.             optr += 12;
  193.         }
  194.         iptr += 4*FB_STRIDE-VID_XRES*2; /* process every fourth scan line */
  195.         optr += 3*VID_XRES;             /* skip to next field scan line */
  196.     }
  197. }
  198.  
  199.